package com.neihe.listenner;

import cn.hutool.core.collection.CollUtil;
import com.aliyun.oss.OSS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.neihe.common.base.ApiException;
import com.neihe.common.constant.Const;
import com.neihe.common.enums.FolderFlagEnum;
import com.neihe.config.OssConfig;
import com.neihe.entity.File;
import com.neihe.entity.UserFile;
import com.neihe.listenner.event.DeleteFileEvent;
import com.neihe.service.IFileService;
import com.neihe.service.IUserFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 删除文件监听器
 */
@Component
@Slf4j
public class DeleteFileEventListener implements ApplicationContextAware {

    @Autowired
    private IFileService fileService;

    @Autowired
    private IUserFileService userFileService;

    @Autowired
    private OssConfig ossConfig;

    @Autowired
    private OSS ossClient;

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    /**
     * 监听文件物理删除事件执行器
     */
    @EventListener(classes = DeleteFileEvent.class)
    public void physicalDeleteFile(DeleteFileEvent event) {
        List<UserFile> allRecords = event.getAllRecords();
        if (CollUtil.isEmpty(allRecords)) return;

        // 找出没有被引用的文件
        List<Long> realFileIds = findAllUnusedRealFileIdList(allRecords);
        if (CollUtil.isEmpty(realFileIds)) return;

        List<File> realFileRecords = fileService.listByIds(realFileIds);
        if (CollUtil.isEmpty(realFileRecords)) return;

        try {
            for (File file : realFileRecords) {
                ossClient.deleteObject(ossConfig.getBucketName(), file.getRealPath());
                // 删除文件记录
                fileService.removeById(file.getFileId());
            }
        } catch (Exception e) {
            log.error("删除文件失败，终止删除: {}", e.getMessage());
            throw new ApiException("内部错误，删除文件失败");
        }
    }

    /**
     * 查找所有没有被引用的真实文件记录ID集合
     *
     * @param allRecords 所有文件记录
     */
    private List<Long> findAllUnusedRealFileIdList(List<UserFile> allRecords) {
        return allRecords.stream()
                .filter(record -> Objects.equals(record.getFolderFlag(), FolderFlagEnum.NO.getCode()))
                .filter(this::isUnused)
                .map(UserFile::getRealFileId)
                .collect(Collectors.toList());
    }

    /**
     * 校验文件的真实文件ID是不是没有被引用了
     *
     * @param record 用户文件信息
     * @return true：被引用 false：没有被引用
     */
    private boolean isUnused(UserFile record) {
        QueryWrapper<UserFile> userFileQueryWrapper = new QueryWrapper<>();
        userFileQueryWrapper.eq("real_file_id", record.getRealFileId());
        return userFileService.count(userFileQueryWrapper) == Const.ZERO_INT;
    }

}
